package cn.jcet.module.sys.realm;

import cn.jcet.common.utils.ActiverUser;
import cn.jcet.common.utils.Constast;
import cn.jcet.module.sys.domain.Permission;
import cn.jcet.module.sys.domain.User;
import cn.jcet.module.sys.service.IPermissionService;
import cn.jcet.module.sys.service.IRoleService;
import cn.jcet.module.sys.service.UserService;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import org.apache.commons.lang3.StringUtils;
import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.AuthenticationInfo;
import org.apache.shiro.authc.AuthenticationToken;
import org.apache.shiro.authc.SimpleAuthenticationInfo;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.authz.SimpleAuthorizationInfo;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;
import org.apache.shiro.util.ByteSource;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Lazy;

import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

public class UserRealm extends AuthorizingRealm {

    /**
     * 使用Lazy加载 使用时候才加载
     */

    @Autowired
    @Lazy //懒加载
    private UserService userService;

    @Autowired
    @Lazy//懒加载
    private IPermissionService permissionService;

    @Autowired
    @Lazy//懒加载
    private IRoleService roleService;

    @Override
    public String getName() {
        return this.getClass().getSimpleName();
    }

    /**
     * 授权
     * @param principalCollection
     * @return
     */
    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {

        SimpleAuthorizationInfo authorizationInfo=new SimpleAuthorizationInfo();

        ActiverUser activerUser = (ActiverUser) principalCollection.getPrimaryPrincipal();

        User user = activerUser.getUser();

        List<String> permissions = activerUser.getPermissions();

        if(user.getType()==Constast.USER_TYPE_SUPER){
            authorizationInfo.addStringPermission("*:*");
        }else {
            if(null != permissions && permissions.size()>0){
                authorizationInfo.addStringPermissions(permissions);
            }
        }

        return authorizationInfo;
    }

    /**
     * 认证
     * @param token
     * @return
     * @throws AuthenticationException
     */
    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
        QueryWrapper<User> query = new QueryWrapper<>();
        String loginName = token.getPrincipal().toString();
        query.eq("loginname",loginName);
        User user = userService.getOne(query);
        if(user != null){
            ActiverUser activerUser = new ActiverUser();
            activerUser.setUser(user);

            //根据用户ID查询percode
            //查询所有菜单权限
            QueryWrapper<Permission> queryWrapper = new QueryWrapper<>();
            queryWrapper.eq("type",Constast.TYPE_PERMISSION);//只查询权限
            queryWrapper.eq("available",Constast.AVAILABLE_TRUE);

            //根据用户ID+角色+权限去查询
            Integer userId =  user.getId();
            //用户id查询
            List<Integer> currentRoleIds = this.roleService.queryUserRoleIdsByUid(userId);
            //根据角色ID取到权限和菜单ID
            Set<Integer> pids = new HashSet<>();
            for (Integer rid:currentRoleIds){
                //查询角色id
                List<Integer> permissionIds = this.roleService.queryRolePermissionIdsByRid(rid);
                pids.addAll(permissionIds);
            }

            List<Permission> list = new ArrayList<>();

            if(pids.size() >0){
                queryWrapper.in("id",pids);
                list = permissionService.list(queryWrapper); //查询全部
            }

            List<String> percodes = new ArrayList<>();
            for (Permission permission : list){
                percodes.add(permission.getPercode());
            }

            activerUser.setPermissions(percodes);

            //盐
            ByteSource salt = ByteSource.Util.bytes(user.getSalt());

            return new SimpleAuthenticationInfo(activerUser,user.getPwd(),salt,this.getName());
        }

        return null;
    }
}
